home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
convrtrs
/
hgrpic
/
a2b.c
next >
Wrap
C/C++ Source or Header
|
1991-05-02
|
9KB
|
336 lines
/*
* A2B.C -- Program to convert Apple// Hi-Res Screen Dumps to
* 320x200x4 .PIC format IBM graphics files. The result is an
* IBM memory map (i.e., a BASIC BLOAD picture).
*
* Program assumes that the input file is an uncompressed
* 280x192 color picture (Apple// HGR memory BSAVE) that
* has already been ported to the IBM environment.
*
* Usage: a2i <applefile> [WAIT]
*
* If no extension is given, an extension of .RAW is assumed.
* Output file generated uses same name as input file, with
* a .PIC extension.
*
* If you add "WAIT" to the command line (or anything really,
* as all I check for is a 2nd parameter) the program will beep
* and wait for a keypress before exiting. Leaving this off the
* command line makes the program work from a batch file for
* multiple conversions.
*/
/* INCLUDES */
#include <stdio.h>
#include <process.h>
#include <dir.h>
#include <conio.h>
#include <dos.h>
#include "cga.h"
/* DEFINES */
#define ERROR -1
#define A_OK 0
/*
* The following are the color equivalents in the CGA pallette that
* closely (relatively) approximate the Apple screen colors. This
* program example thinks in the cyan/magenta/white pallette, but can
* easily be adapted to the green/red/yellow.
*/
#define _A_BLACK 0
#define _A_VIOLET _RED
#define _A_GREEN _BLUE
#define _A_BLUE _BLUE
#define _A_ORANGE _RED
#define _A_WHITE _WHITE
/* GLOBALS */
UBYTE apple_memory[192][40]; /* Apple "memory" map */
int apple_lines[8][3] = {
{ 0, 64, 128 },
{ 8, 72, 136 },
{ 16, 80, 144 },
{ 24, 88, 152 },
{ 32, 96, 160 },
{ 40, 104, 168 },
{ 48, 112, 176 },
{ 56, 120, 184 }
}; /* Index table for Apple memory */
/*
* The Apple HGR screen is wonderfully convoluted (in several ways). For
* instance, the color of a particular pixel on the Apple screen depends
* upon THREE (3) things:
*
* 1) Is the Apple screen byte an EVEN or ODD byte on the scanline?
* 2) Is the MSB of the screen byte SET?
* 3) Is the pixel/bit in question on an EVEN or ODD column?
*
* Pretty confusing, huh? a2i_colors[][][] handles this as follows:
*
* Pixel_color = a2i_colors[EVEN/ODD byte?][MSB SET?][EVEN/ODD column?]
*/
int a2i_colors[2][2][2] = {
{ /* EVEN byte */
{ _A_VIOLET, _A_GREEN }, /* MSB not set */
{ _A_BLUE , _A_ORANGE } /* MSB set */
},
{ /* ODD byte */
{ _A_GREEN , _A_VIOLET }, /* MSB not set */
{ _A_ORANGE, _A_BLUE } /* MSB set */
}
};
/* FUNCTIONS */
/*
* load_apple_raw() -- Take a raw BSAVE file and load it into the temporary
* memory buffer. This routine unscrambles Apple's
* memory mapping at the same time, so that the buffer
* becomes consecutive, as opposed to Apple's convoluted
* skipping from block to block.
*/
int load_apple_raw(const char *fname)
{
int i, vline, block, mline = 0;
FILE *fsave;
if((fsave = fopen(fname, "rb")) == NULL)
return ERROR;
rewind(fsave);
/*
* Even though we're dealing with Apple graphics, the screen map is still
* heavily tied to the text screen layout. Apple's HGR screen is divided
* into 24 "blocks" of 8 lines per block (the main reason why when you do
* a BLOAD to the HGR screen, you get the infamous "venetian blind" load.
* Unfortunately, we end up stepping through memory (scanline-wise) as
* follows:
*
* 0, 64, 128, 8, 72, 136, ..., 184, 1, 65, 129, ...
*
* (i.e. line 0 is the first line of the file, line 1 is the 25th line of
* the file...wonderful, right?)
*
* If that isn't enough, every there are an additional 8 bytes of garbage
* space every 3 scanlines (reminiscent of IBM's CGA architecture).
*
* The easiest way I found to handle this is to create the apple_lines[][]
* table of base scanlines and index off of them.
*/
for(block=0;block<8;block++)
for(mline=0;mline<24;mline++)
{
vline = apple_lines[mline / 3][mline % 3] + block;
for(i=0;i<40;i++)
apple_memory[vline][i] = fgetc(fsave);
if((mline % 3) == 2)
for(i=0;i<8;i++)
fgetc(fsave);
}
fclose(fsave);
return A_OK;
}
/*
* apple_2_ibm() -- Take the "Apple map" image in the apple_memory[][]
* array and translate it into an CGA mode 4 image on
* the display. xoff and yoff are pixel offsets on the
* CGA screen that result in the Apple image (280x192)
* being displayed dead center on the CGA screen (320x200).
*/
void apple_2_ibm(void)
{
int xoff = 20, yoff = 4;
int i, j, k, which, line[280];
UBYTE abyte, abit;
for(i=0;i<192;i++) /* 192 lines in an Apple HGR screen */
{
/*
* The first thing we do is convert an Apple scanline to a CGA scanline,
* meaning that we must decode each Apple byte (7 pixels per byte) into
* CGA pixels. line[] is the line buffer, each index holding one pixel's
* color value.
*/
for(j=0;j<40;j++) /* 280 pixels/line = 40 Apple bytes */
{
abyte = apple_memory[i][j]; /* Get an Apple byte */
which = (abyte & 0x80) == 0x80; /* Which Apple color scheme? */
/*
* Now, cycle through the Apple byte one pixel at a time. Since Apple
* bytes are encoded "backwards" to IBM screenlines, the least significant
* bit of the Apple byte is the far right pixel of the IBM byte.
* Therefore, the decompression process works as follows:
*
* 1) Grab LSB of Apple byte.
* 2) Set equivalent EGA pixel to correct Apple color (remember, Apple
* colors depend upon: A) whether the pixel is in an even or odd
* column (on the Apple screen), and B) whether the high bit of the
* Apple byte is set or not.
* 3) Shift Apple byte right one bit.
* 4) Repeat steps 1-3 for remaining 6 pixels in Apple byte
*/
for(k=0;k<7;k++) /* 7 pixels per Apple byte */
{
abit = abyte & 0x01;
line[j*7 + k] = a2i_colors[j % 2][which][k % 2] * abit;
abyte >>= 1;
}
}
/*
* Now that we've built a CGA screen line, write it out to screen memory.
* The actual color displayed on the Apple screen depends not only on
* whether a given pixel is set or not, but also on whether adjacent
* pixels are set (if two adjacent pixels are on, the resulting color is
* WHITE, *not* the individual pixel colors). The algorithm is:
*
* IF (current pixel first on scanline)
* Check the next pixel
* IF (both pixels aren't black)
* Write out a white pixel
* ELSE
* Write out the color of the first pixel
* ELSE IF (current pixel last on scanline)
* Check the previous pixel
* IF (both pixels aren't black)
* Write out white pixel
* ELSE
* Write out the color of the last pixel
* ELSE
* IF (current pixel not black) AND (previous OR next pixel not black)
* Write out a white pixel
* ELSE IF (current pixel black) AND (previous pixel same color as
* next pixel)
* Write out color of previous pixel
* ELSE
* Write out color of current pixel
*
* The convoluted part of the algorithm (the last part of the main IF
* structure) is because 2 ON pixels with 1 OFF pixel between them on
* the Apple screen are seen as a solid color (no gaps).
*/
for(k=0;k<280;k++)
{
if(k == 0)
{
if(line[k]!=_A_BLACK && line[k+1]!=_A_BLACK)
put_pixel(k + xoff, i + yoff, _A_WHITE);
else
put_pixel(k + xoff, i + yoff, line[k] );
}
else
if(k == 279)
{
if(line[k]!=_A_BLACK && line[k-1]!=_A_BLACK)
put_pixel(k + xoff, i + yoff, _A_WHITE);
else
put_pixel(k + xoff, i + yoff, line[k] );
}
else
{
if(line[k]!=_A_BLACK && (line[k-1]!=_A_BLACK || line[k+1]!=_A_BLACK))
put_pixel(k + xoff, i + yoff, _A_WHITE );
else
if(line[k]==_A_BLACK && line[k-1]==line[k+1])
put_pixel(k + xoff, i + yoff, line[k-1]);
else
put_pixel(k + xoff, i + yoff, line[k] );
}
}
}
}
/* MAIN */
void main(int argc, char **argv)
{
char drive[MAXDRIVE], dir[MAXDIR], file[MAXFILE], ext[MAXEXT];
char infile[13], outfile[13];
if(argc == 1)
{
printf("Usage: a2b <applefile> [WAIT]\n");
exit(0);
}
init_cgfx(0x04); /* Initialize CGA mode 4 */
fnsplit(argv[1], drive, dir, file, ext);
if(ext[0] == '\0')
fnmerge(infile, "", "", file, ".RAW");
else
fnmerge(infile, "", "", file, ext );
fnmerge(outfile, "", "", file, ".PIC");
gotoxy(12, 10); printf("Loading...");
if(load_apple_raw(infile) != ERROR)
{
gotoxy(12, 10); printf("Converting...");
apple_2_ibm();
sleep(2);
save_pic(outfile);
cls();
fload_pic(outfile);
if(argc == 3)
{
putch(7);
getch();
}
}
else
printf("Error...");
mode(3);
}